import cv2
import numpy as np
import pandas as pd
from PySide6.QtCore import Qt, QRect
from PySide6.QtGui import QPixmap, QImage
from PySide6.QtWidgets import QTableWidgetItem

import re

from wordcloud import WordCloud

from toast.toast import DialogOver
from utils.utils import validate_color_format
from PIL import Image

def readFile(self, page, file_path):
    # 不能是中文路径
    if re.search(r'[\u4e00-\u9fa5]', file_path):
        raise ValueError("文件路径不能是中文哟！")


    # 如果是读取表格
    if page == 0:
        readTable(self, file_path)

    # 读取图像数据
    if page == 1:
        readImage(self, file_path)

    # 读取字体
    if page == 2:
        readFont(self, file_path)

    # 获取文件名
    file_name = file_path.split('/')[-1]  # 分割路径并取最后一部分作为文件名带扩展名
    return file_name

def readTable(self,file_path):
    dataframe = pd.read_excel(file_path)
    headers = dataframe.columns[:4]  # 读取前四列数据
    # print(headers)
    content = ''
    for index, row in dataframe.iterrows():
        # print(row)
        if pd.notnull(row[0]):  # 首列数据不为空时读取
            content += ' '.join(str(cell) for cell in row[:4]) + '\n'
        else:
            break

    # 假设 content 是你读取到的文本内容
    rows = content.split('\n')  # 按换行符分割文本内容为行
    if self.tableWidget.rowCount() < len(rows):
        self.tableWidget.setRowCount(len(rows))  # 设置表格行数

    for i, row_data in enumerate(rows):
        cells = row_data.split()  # 按空格分割每行数据
        for j, cell_data in enumerate(cells):
            item = QTableWidgetItem(cell_data)  # 创建一个QTableWidgetItem对象，并设置文本内容
            self.tableWidget.setItem(i, j, item)  # 将QTableWidgetItem对象放入对应的单元格

    # 如果需要调整表格大小
    # self.tableWidget.resizeColumnsToContents()
    self.tableWidget.resizeRowsToContents()


def showImg(img, label):
    # 将 OpenCV 图像数据转换为 QImage 对象 （）
    height, width, _ = img.shape  # 这里优化一下！
    w = label.geometry().width()
    h = label.geometry().height()



    # 根据图像宽高比例进行缩放
    if width / w > height / h:
        scal = w / width
        nw = w
        nh = int(scal * height)
        resized_image = cv2.resize(img, (nw, nh))
    else:
        scal = h / height
        nw = int(scal * width)
        nh = h
        resized_image = cv2.resize(img, (nw, nh))

    # 将 OpenCV 图像从 BGR 格式转换为 RGB 格式
    frame = cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB)

    # 创建 QImage 对象
    qimage = QImage(frame.data, frame.shape[1], frame.shape[0], frame.shape[1] * frame.shape[2],
                    QImage.Format_RGB888)

    # 在标签窗口中显示图像
    label.setPixmap(QPixmap.fromImage(qimage))


def readImage(self, file_path):
    self.img_path = file_path  # 设置图像路径
    mask = createMask(file_path)

    # 获取标签窗口的大小——显示图片
    showImg(mask, self.img_1)


# 读取字体
def readFont(self, file_path):
    self.font_path = file_path # 字体路径

    # 获取文件名
    file_name = file_path.split('/')[-1]  # 分割路径并取最后一部分作为文件名带扩展名
    # 设置样式表
    style_sheet = '''
        background-color: rgb(238, 242, 255);
        border: 2px solid rgb(255, 255, 255);
        border-radius: 15px;
        color: rgba(0, 0, 0, 0.2);
        font-size: 8px;
        font: 8pt "Microsoft YaHei UI";
    '''
    self.img_2.setStyleSheet(style_sheet)
    self.img_2.setText(file_name)

# 创建词云字典
def createWordDict(self):
    # 创建词频字典 与 颜色字典
    word_frequencies = {}
    word_color = {}
    for row in range(self.tableWidget.rowCount()):
        item_word = self.tableWidget.item(row, 0)
        item_frequency = self.tableWidget.item(row, 1)
        item_color = self.tableWidget.item(row, 2)

        # 检查单元格是否为空
        if item_word is not None and item_frequency is not None and item_color is not None:
            word = item_word.text()
            frequency_text = item_frequency.text()
            color_text = item_color.text()

            try:
                # 进一步检查频率是否可以转换为整数
                frequency = int(frequency_text)
                word_frequencies[word] = frequency

            except ValueError:
                # 如果频率不是一个有效的整数，打印错误信息并跳过
                DialogOver(parent=self,
                           text=f"该词语 '{word}'的词频 '{frequency_text}'- 无法转换为整数。",
                           title="运行失败", flags="danger")
                return None

            # 检查 item_color的格式
            if validate_color_format(color_text) is False:
                DialogOver(parent=self, text=f"该词语 '{word}'的颜色 '{color_text}'- 格式非法。", title="运行失败", flags="danger")
                return None
            word_color[word] = color_text

    # 如果数据为空
    if word_frequencies == {} or word_color == {}:
        DialogOver(parent=self,
                   text=f"表格数据为空！",
                   title="运行失败", flags="danger")
        return None
    self.word_frequencies = word_frequencies
    self.word_color = word_color

    # print(word_frequencies)
    # print(word_color)
    return 1

# 创建掩膜
def createMask(img_path):
    # 读取PNG图片，包括alpha通道
    img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)

    # 创建一个新的三通道图像，背景为白色
    mask = np.ones(img.shape, dtype=np.uint8) * 255

    # 将区域设置为黑色
    mask[:, :, :3] = [0, 0, 0]
    # 将透明区域改为白色
    mask[img[:, :, 3] == 0] = [255, 255, 255, 255]
    # 去除 alpha 通道
    mask = cv2.cvtColor(mask, cv2.COLOR_RGBA2RGB)
    return mask

# 创建词云图
def createImg(self):

    # 是否自定义背景颜色
    if self.is_use_bgcolor:
        color_list = self.bg_color_input.text().split(",")
        r, g, b = int(color_list[0]), int(color_list[1]), int(color_list[2])
    else:
        r, g, b = (175, 221, 247)

    # 读取PNG图片，包括alpha通道
    img = cv2.imread(self.img_path, cv2.IMREAD_UNCHANGED)

    # 创建一个新的三通道图像，背景为白色
    mask = np.ones(img.shape, dtype=np.uint8) * 255

    # 将区域设置为黑色
    mask[:, :, :3] = [0, 0, 0]
    # 将透明区域改为白色  (255代表Alpha通道的值，最大值为255，表示完全不透明。
    mask[img[:, :, 3] == 0] = [255, 255, 255, 255]

    height, width = mask.shape[:2]  # 获取图像的高度和宽度

    color_mask = np.ones(img.shape, dtype=np.uint8) * 255
    color_mask[:, :, :3] = [b, g, r]
    color_mask[img[:, :, 3] == 0] = [255, 255, 255, 0]


    # 定义一个函数，根据词语内容返回颜色
    def custom_color_func(word, font_size, position, orientation, random_state=None, **kwargs):
        if word in self.word_color:
            return self.word_color[word]
        else:
            return 'black'  # 如果词语不在字典中，则返回黑色

    # 词语函数
    # 定义一个基础的配置字典，包含所有WordCloud实例共有的参数
    base_config = {
        "mask": mask,  # 使用反转后的图像作为遮罩
        "background_color": None,  # 使背景透明
        "mode": "RGBA",  # 启用透明模式
        "width": width,  # 宽度
        "height": height,  # 高度
        "font_path": self.font_path,  # 指定字体路径（确保路径没有中文）
        "prefer_horizontal": 1,  # 字体水平排版
        "stopwords": None,  # 屏蔽词
        "repeat": False,
    }

    # 如果需要使用色卡，向配置字典中添加colormap参数
    if self.is_use_color:
        base_config["colormap"] = self.color_style_box.currentText()
        if self.color_style_box.currentText() is None or self.color_style_box.currentText() == '':
            DialogOver(parent=self, text='还未选择色卡样式哟！', title="运行失败", flags="danger")
            return
    # 设置自定义颜色
    else:
        base_config["color_func"] = custom_color_func
    # 如果使用 重复单词
    if self.is_use_reapt is True:
        base_config["repeat"] = True



    # 使用更新后的配置字典创建WordCloud实例
    wordcloud = WordCloud(**base_config)
    # 根据词频生成词云
    wordcloud.generate_from_frequencies(self.word_frequencies)

    # 将词云图像转换为PIL图像
    wordcloud_pil = wordcloud.to_image()

    # 将 OpenCV 图像从 BGRA 转换为 RGBA
    color_mask_rgb = cv2.cvtColor(color_mask, cv2.COLOR_BGRA2RGBA)

    # 将color_mask转换为PIL图像，并确保是RGBA模式
    color_mask_pil_rgba = Image.fromarray(color_mask_rgb, mode="RGBA")

    # 将词云图像覆盖到color_mask上
    composite_img = Image.alpha_composite(color_mask_pil_rgba, wordcloud_pil)
    self.composite_img = composite_img


    #-------------------------------------------------------
    # 转换图片
    wordcloud_img = wordcloud.to_image()
    # 将color_mask转换为PIL图像
    color_mask_pil = Image.fromarray(cv2.cvtColor(color_mask, cv2.COLOR_BGR2RGB))

    # 确保wordcloud_img是RGBA模式的PIL图像
    if wordcloud_img.mode != "RGBA":
        wordcloud_img = wordcloud_img.convert("RGBA")

    # 将词云图像覆盖到底图上
    composite_img = Image.alpha_composite(color_mask_pil.convert("RGBA"), wordcloud_img)


    # 将 PIL 图像转换为 OpenCV 读取的图片格式
    image_cv = cv2.cvtColor(np.array(composite_img), cv2.COLOR_RGB2BGR)

    # 获取标签窗口的大小——显示图片
    showImg(image_cv, self.pre_img)
